import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { RootState } from "./store";
import { getRequest } from "../util/Auth";
import { NulResponse, createEmptyRequest, createRequest } from "./common";

type WarehouseStatus = 'open' | 'closed' | 'suspended';

interface WarehouseEntry {
  id: number;
  name: string;
  type: string;
  address: string;
  status: WarehouseStatus;
  authority: number;
}

interface WarehouseState {
  fetched: boolean;
  entries: WarehouseEntry[];
}

interface CreateWarehouseRequest {
  name: string;
  type: string;
  address: string;
  status: WarehouseStatus;
  authority: number;
}

interface CreateWarehouseResponse {
  id: number;
}

interface DeleteWarehouseRequest {
  id: number;
}

const initialWarehouseState: WarehouseState = {
  fetched: false,
  entries: []
}

export const fetchAllWarehouse = createAsyncThunk('api/fetchAllWarehouse', async (_: void, { getState, rejectWithValue }) => {
  const state = getState() as RootState;
  try {
    const request = getRequest(state);
    const response = await request.post<NulResponse<WarehouseEntry[]>>('/service/warehouse/fetchAll',
      createEmptyRequest());
    return response.data;
  }
  catch (e) {
    return rejectWithValue(e);
  }
});

export const createWarehouse = createAsyncThunk('api/createWarehouse', async (warehouse: CreateWarehouseRequest, { getState, rejectWithValue }) => {
  const state = getState() as RootState;
  try {
    const request = getRequest(state);
    const response = await request.post<NulResponse<CreateWarehouseResponse>>('/service/warehouse/createEntry',
      createRequest(warehouse));
    return response.data;
  }
  catch (e) {
    return rejectWithValue(e);
  }
});

export const deleteWarehouse = createAsyncThunk('api/deleteWarehouse', async (deleteRequest: DeleteWarehouseRequest, { getState, rejectWithValue }) => {
  const state = getState() as RootState;
  try {
    const request = getRequest(state);
    const response = await request.post<NulResponse<null>>('/service/warehouse/deleteEntry',
      createRequest(deleteRequest));
    return response.data;
  }
  catch (e) {
    return rejectWithValue(e);
  }
});

export const modifyWarehouse = createAsyncThunk('api/modifyWarehouse', async (warehouse: WarehouseEntry, { getState, rejectWithValue }) => {
  const state = getState() as RootState;
  try {
    const request = getRequest(state);
    const response = await request.post<NulResponse<null>>('/service/warehouse/modifyEntry',
      createRequest(warehouse));
    return response.data;
  }
  catch (e) {
    return rejectWithValue(e);
  }
})

const warehouseSlice = createSlice({
  name: 'warehouse',
  initialState: initialWarehouseState,
  reducers: {

  },
  extraReducers: (builder) => {
    builder.addCase(createWarehouse.rejected, (state, action) => {
      console.error(action.error);
    }).addCase(createWarehouse.fulfilled, (state, action) => {
      state.entries.push({
        id: action.payload.result.id,
        ...action.meta.arg
      });
    }).addCase(fetchAllWarehouse.rejected, (state, action) => {
      console.error(action.error);
    }).addCase(fetchAllWarehouse.fulfilled, (state, action) => {
      state.fetched = true;
      state.entries = action.payload.result;
    }).addCase(deleteWarehouse.rejected, (state, action) => {
      console.error(action.error);
    }).addCase(deleteWarehouse.fulfilled, (state, action) => {
      const result: WarehouseEntry[] = [];
      state.entries.forEach((value) => {
        if (value.id !== action.meta.arg.id) {
          result.push(value);
        }
      });
      state.entries = result;
    }).addCase(modifyWarehouse.rejected, (state, action) => {
      console.error(action.error);
    }).addCase(modifyWarehouse.fulfilled, (state, action) => {
      const index: number = state.entries.findIndex(item => item.id === action.meta.arg.id);
      if (index !== -1) {
        state.entries[index] = action.meta.arg;
      }
    });
  }
});

export type { WarehouseEntry, WarehouseStatus };
export const selectWarehouseFetched = (state: RootState) => state.warehouseManagementReducer.fetched;
export const selectWarehouseEntries = (state: RootState) => state.warehouseManagementReducer.entries;
export default warehouseSlice.reducer;
